﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace MainGameModule
{
    public class SplineAnimation : Control
    {
        public static readonly DependencyProperty FramesPerSecondProperty = DependencyProperty.Register("FramesPerSecond", typeof(double), typeof(SplineAnimation), null);
        public static readonly DependencyProperty NumberOfImagesProperty = DependencyProperty.Register("CountOfImages", typeof(int), typeof(SplineAnimation), null);
        public static readonly DependencyProperty ImagesDirectoryProperty = DependencyProperty.Register("ImagesDirectory", typeof(string), typeof(SplineAnimation), null);
        public static readonly DependencyProperty ImagesCommonPatternProperty = DependencyProperty.Register("ImagesCommonPattern", typeof(string), typeof(SplineAnimation), null);
        public static readonly DependencyProperty ImagesExtentionProperty = DependencyProperty.Register("ImagesExtention", typeof(string), typeof(SplineAnimation), null);
        public static readonly DependencyProperty AutoReverseProperty = DependencyProperty.Register("AutoReverse", typeof(bool), typeof(SplineAnimation), new PropertyMetadata(true));

        public double FramesPerSecond
        {
            get { return (double)GetValue(FramesPerSecondProperty); }
            set { SetValue(FramesPerSecondProperty, value); }
        }

        public int CountOfImages
        {
            get { return (int)GetValue(NumberOfImagesProperty); }
            set { SetValue(NumberOfImagesProperty, value); }
        }

        public string ImagesDirectory
        {
            get { return (string)GetValue(ImagesDirectoryProperty); }
            set { SetValue(ImagesDirectoryProperty, value); }
        }

        public string ImagesCommonPattern
        {
            get { return (string)GetValue(ImagesCommonPatternProperty); }
            set { SetValue(ImagesCommonPatternProperty, value); }
        }

        public string ImagesExtention
        {
            get { return (string)GetValue(ImagesExtentionProperty); }
            set { SetValue(ImagesExtentionProperty, value); }
        }

        public bool AutoReverse
        {
            get { return (bool)GetValue(AutoReverseProperty); }
            set { SetValue(AutoReverseProperty, value); }
        }

        private Image image;
        private double averageInterval;
        private long lastTick = DateTime.Now.Ticks;
        private int currentImg = 0;
        private int completedCycles = 0;

        public SplineAnimation()
        {
            this.DefaultStyleKey = typeof(SplineAnimation);
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            CompositionTarget.Rendering -= new EventHandler(this.CompositionTarget_Rendering);
            this.image = this.GetTemplateChild("SplineImage") as Image;
            this.averageInterval = TimeSpan.TicksPerSecond / this.FramesPerSecond;
            CompositionTarget.Rendering += new EventHandler(this.CompositionTarget_Rendering);
        }

        private void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            if (this.AutoReverse || (this.completedCycles == 0))
            {
                long now = DateTime.Now.Ticks;

                if (now - this.lastTick < this.averageInterval)
                {
                    return;
                }

                if (this.currentImg == this.CountOfImages)
                {
                    this.currentImg = 0;
                    this.completedCycles++;

                    if (this.AutoReverse)
                    {
                        this.image.Source = new BitmapImage(new Uri(this.GetNexImageName(this.currentImg), UriKind.RelativeOrAbsolute));
                    }
                }
                else
                {
                    this.image.Source = new BitmapImage(new Uri(this.GetNexImageName(this.currentImg), UriKind.RelativeOrAbsolute));
                }

                this.lastTick = now;
                this.currentImg++;
            }
        }

        private string GetNexImageName(int index)
        {
            return String.Format("{0}/{1}{2}.{3}", this.ImagesDirectory, this.ImagesCommonPattern, index, this.ImagesExtention);
        }
    }
}